package com.zhg.shortlink.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.zhg.shortlink.domain.dto.ApiResponse;
import com.zhg.shortlink.domain.dto.CreateShortUrlRequest;
import com.zhg.shortlink.domain.dto.CreateShortUrlResponse;
import com.zhg.shortlink.service.ShortUrlService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Objects;

/**
 * @author 朱洪刚
 * @version 1.0
 * @data 2025/10/20 13:39
 */
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/shortUrl")
@RestController
public class ShortUrlController {

    private final ShortUrlService shortUrlService;

    /**
     * 创建短链
     */
    @PostMapping("/api/short-url")
    public ApiResponse<CreateShortUrlResponse> createShortUrl(
            @Valid @RequestBody CreateShortUrlRequest request) {
        CreateShortUrlResponse response = shortUrlService.createShortUrl(request);
        return ApiResponse.success("短链创建成功", response);
    }

    /**
     * 短链跳转
     */
    @GetMapping("/{shortCode}")
    @SentinelResource(
            value = "redirectShortUrl",
            blockHandler = "redirectBlockHandler",
            fallback = "redirectFallback"
    )
    public void redirect(@PathVariable("shortCode") String shortCode, HttpServletResponse response)
            throws IOException {

        log.info("shortCodeCount");
        try {
            String shortUrlInfo = shortUrlService.getOriginUrl(shortCode);
            if (Objects.isNull(shortUrlInfo)) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, "短链不存在或已过期");
                return;
            }

            // 302重定向，优化缓存策略
            response.setStatus(HttpServletResponse.SC_FOUND);
            response.setHeader("Location", shortUrlInfo);
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");
        } catch (Exception e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "系统内部错误");
        }
    }

    // Sentinel 限流处理
    public void redirectBlockHandler(String shortCode,
                                     HttpServletRequest request,
                                     HttpServletResponse response,
                                     BlockException ex) throws IOException {
        response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
        response.getWriter().write("访问过于频繁，请稍后重试");
    }

    // Sentinel 降级处理
    public void redirectFallback(String shortCode,
                                 HttpServletRequest request,
                                 HttpServletResponse response,
                                 Throwable ex) throws IOException {
        response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());
        response.getWriter().write("服务暂时不可用，请稍后重试");
    }
}
